'''
@Description: In User Settings Edit
@Author: your name
@Date: 2019-07-09 10:41:46
@LastEditTime: 2019-08-31 16:54:06
@LastEditors: Please set LastEditors
'''
from server.pao_python.pao.service.data.mongo_db import MongoService, MongoFilter, C, N, F, as_date
from ...service.buss_pub.bill_manage import BillManageService, OperationType, TypeId, Status
from ...pao_python.pao.service.security.security_utility import get_current_account_id
from ...service.common import insert_data, find_data, update_data, delete_data, get_condition, get_info, get_random_id,get_user_id_or_false
from ...pao_python.pao.service.security.security_utility import get_current_account_id, get_current_role_id, get_current_indentify
from ...pao_python.pao.service.security.security_service import RoleService
import hashlib
import re
import datetime
import uuid
import pandas as pd
from ...pao_python.pao.data import process_db, dataframe_to_list, DataProcess, DataList
from ...service.buss_pub.user_manage import AccountData, AccountRoleData, LoginAuthenticateData, RoleData
from ...service.mongo_bill_service import MongoBillFilter
'''
@Description: In User Settings Edit
@Author: your name
@Date: 2019-07-09 10:41:46
@LastEditTime: 2019-07-09 10:41:46
@LastEditors: your name
'''
# -*- coding: utf-8 -*-

'''
人员及组织机构管理函数
'''


class UserType:
    ''' 人员类型

    Attribute:
        Personnel           人员
        Organizational      组织机构
    '''
    Personnel = '1'
    Organizational = '2'

class UserCategory:
    ''' 人员类别 
    
        Attribute
        Elder       长者
        StaffMember     工作人员
        Family      家属
        PlatformAdministrator  平台管理员
    '''
    Elder = '长者'
    StaffMember = '工作人员'
    Family = '家属'
    PlatformAdministrator = '平台管理员'




class User:
    ''' 用户对象类 '''

    def create_user(self, user):
        ''' 创建用户 '''
        if 'id' in user.keys():
            self.id = user['id']
        self.name = user['name']
        self.personnel_info = user['id_card']
        self.personnel_info = user['id_card_type']
        self.personnel_info = {}
        self.personnel_info.comment = user['comment']
        self.personnel_info.telephone = user['telephone']
        self.personnel_info.contacts = user['contacts']
        self.personnel_info.address = user['address']
        self.personnel_info.personnel_category = user['personnel_category']
        
    def get_personnel(self, personnel):
        ''' 获取人员 '''
        self.create_user(personnel)
        self.personnel_type = UserType.Personnel
        return self.__dict__

    def get_organizational(self, organization):
        ''' 获取组织 '''
        self.create_user(organization)
        self.organization_info = {**organization}
        self.personnel_type = UserType.Organizational
        return self.__dict__


class PersonnelOrganizationalService(MongoService):
    ''' 人员组织机构服务 '''

    plat_visitor_role = '8926d292-5075-11e9-9e78-0c9d92157df1'

    def __init__(self, db_addr, db_port, db_name,db_user, db_pwd,  inital_password, session):
        DataProcess.__init__(self, db_addr, db_port, db_name,db_user, db_pwd)
        # self.db_name = db_name
        self.inital_password = inital_password
        self.session = session
        self.role_service = RoleService(
            db_addr, db_port, db_name, db_user, db_pwd,inital_password, session)
        self.bill_manage_service = BillManageService(
            db_addr, db_port, db_name, db_user, db_pwd,inital_password, session)

    def get_organization_id(self):
        '''通过session拿登录账户的所属organization_id'''
        # account_id = get_current_account_id(self.session)
        role_id = get_current_role_id(self.session)
        _filter = MongoBillFilter()
        _filter.match_bill(C('role_id') == role_id)
        res = self.query(_filter, 'PT_Role')
        return res[0]['organization_id']

    def __relate_account_user(self, telephone, account_id):
        '''通过电话号码查询是否已有user登记，若已有登记则更新增加account_id,否则在user表中新增一条数据'''
        res = 'Fail'
        _filter = MongoBillFilter()
        _filter.match_bill((C('telephone') == telephone) & (C('personnel_type') == UserType.Personnel))
        user_info = self.query(_filter, 'PT_User')
        if len(user_info) == 0:
            user_id = get_random_id()
            new_user_data = {'id': user_id, 'telephone': telephone,
                             'personnel_type': UserType.Personnel, 'account_id': account_id}
            bill_id = self.bill_manage_service.add_bill(
                OperationType.add.value, TypeId.user.value, new_user_data, 'PT_User')
        else:
            update_user_data = {'id': user_info[0]['id'], 'account_id': account_id}
            bill_id = self.bill_manage_service.add_bill(
                OperationType.update.value, TypeId.user.value, update_user_data, 'PT_User')
        if bill_id:
            res = 'Success'
        return res

    def __add_new_account(self, basic_data, role_id):
        '''账户注册基本操作（默认手机号码未绑定任何account，手机号码校验时保证了这一点）
        包括：（1）User表检索是否存在电话，若存在则直接将该user_id进行绑定到account中，否则新建一个user
              （2）增加账户数据和登录验证表数据
              （3）为该用户绑定角色
        Args :
        basic_data : 关键字 account_name,password,telephone
        role_id : 角色id
        '''
        res = 'Fail'
        account_id = get_random_id()
        new_account_data = AccountData(account_id, basic_data['telephone'], basic_data['account'])
        new_login_data = LoginAuthenticateData(account_id, basic_data['password'])
        new_account_role_data = AccountRoleData(account_id, role_id)
        user_res = self.__relate_account_user(basic_data['telephone'], account_id)
        bill_id = self.bill_manage_service.add_bill(OperationType.add.value, TypeId.user.value,
                                                    [new_account_data, new_login_data, new_account_role_data],
                                                    ['PT_Account', 'PT_Login_Authenticate', 'PT_Account_Role'])
        if user_res and bill_id:
            res = 'Success'
        return res

    def add_new_visitor(self, data):
        '''游客注册操作 , 绑定平台游客角色
        Args :
        data : 关键字 account_name,password,telephone
        '''
        return self.__add_new_account(data, self.plat_visitor_role)

    def add_new_user_by_admin(self, data):
        '''管理员新增账户并绑定角色
        Args :
        data : 关键字 account_name,password,telephone,role_id
        '''
        return self.__add_new_account(data, data['role_id'])

    def __add_role_account_data(self, account_id, role_id):
        res = 'Fail'
        new_account_role_data = AccountRoleData(account_id, role_id)
        bill_id = self.bill_manage_service.add_bill(OperationType.add.value, TypeId.user.value,
                                                    new_account_role_data, 'PT_Account_Role')
        if bill_id:
            res = 'Success'
        return res

    def add_role_for_org_user_by_admin(self, account_id, role_id):
        '''为已有机构角色的用户增加角色（增加的为同一机构的角色）'''
        return self.__add_role_account_data(account_id, role_id)

    def add_role_for_exit_user_by_admin(self, telephone, identify_code, role_id):
        '''为已有账户的用户绑定该机构的角色，需通过手机号码验证身份通过后方可绑定'''
        res = 'Fail'
        if get_current_indentify(self.session) == identify_code:
            _filter = MongoBillFilter()
            _filter.match_bill(C('mobile') == telephone)
            account_data = self.query(_filter, 'PT_Account')
            if len(account_data) > 0:
                account_id = account_data[0]['id']
                res = self.__add_role_account_data(account_id, role_id)
        return res

    def add_new_organization_by_plat(self, org_data, role_data, user_data):
        '''平台新增机构
        包括：（1）新增机构信息
              （2）为该机构新增管理员角色
              （3）为机构绑定一个用户做管理员(默认平台有权限看到所有用户)
        Args :
        org_data：新增机构基础数据
        role_data:新增角色数据，关键字包含role_name,permission
        user_data：若新增用户，关键字为：account_name,password,telephone；若选择已有用户：关键字为account_id
        '''
        res = 'Fail'
        organization_id = get_random_id()
        new_organization_data = dict(org_data, **{'id': organization_id, 'personnel_type': UserType.Organizational})
        role_id = get_random_id()
        new_role_data = dict(role_data, **{'id': role_id, 'organization_id': organization_id})
        bill_add = self.bill_manage_service.add_bill(OperationType.add.value, TypeId.user.value,
                                                     [new_organization_data, new_role_data], ['PT_User', 'PT_Role'])
        if 'account_id' in list(user_data.keys()):
            bill_add2 = self.__add_role_account_data(user_data['account_id'], role_id)
        else:
            bill_add2 = self.add_new_user_by_admin(dict(user_data, **{'role_id': role_id}))
        if bill_add and bill_add2:
            res = 'Success'
        return res

    def get_login_role_list(self):
        '''登录成功后，查询该账户的所有角色'''
        account_id=get_current_account_id(self.session)
        _filter = MongoBillFilter()
        _filter.match(C('account_id') == account_id)\
               .lookup('PT_Role','role_id','id','role_info')\
               .lookup_bill('PT_User','role_info.organization_id','id','org_info')\
               .project({'_id':0,'role_id':1,'role_name':'$role_info.role_name','org_name':'$org_info.name'})
        res=self.query(_filter,'PT_Account_Role')
        return res
    
    def get_account_list(self):
        '''获取用户列表（获取该账号所在机构的人员列表）[需考虑平台管理员能看到全部的情况]'''
        pass

    def get_role_list(self):
        '''获取角色列表（获取该账号所在机构的角色列表） [需考虑平台管理员能看到全部的情况]'''
        pass

    def add_new_role(self,role_data):
        '''新增角色
        Args :
        role_data:关键字包含role_name,permission
        '''
        res='Fail'
        organization_id=self.get_organization_id()
        new_data=dict(role_data,**{'id':get_random_id(),'organization_id':organization_id})
        bill_id = self.bill_manage_service.add_bill(OperationType.add.value, TypeId.user.value,new_data, 'PT_Role')
        if bill_id:
            res = 'Success'
        return res


    def get_personnel_list(self, condition, page, count):
        '''获取人员列表

        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'name', 'id_card']
        values = self.get_value(condition, keys)
        _filter = MongoFilter()
        _filter.match((C('id') == values['id']) & (C('personnel_type') == UserType.Personnel))\
            .match((C('bill_status') == 'valid') & (C('name').like(values['name'])) & (C('id_card') == values['id_card']))\
            .project({'_id': 0})
        res = self.page_query(
            _filter, 'PT_User', page, count)
        print("数据》》》》》》》》",res)
        return res

    def update_personnel(self, personnel):
        '''新增/修改人员

        Arguments:
            personnel   {dict}      条件
        '''

        res = 'Fail'

        user = User().get_personnel(personnel)
        account_id = get_random_id()
        account = AccountData(account_id, user['telephone']).to_dict()
        account_role = AccountRoleData(account_id, user['role_id']).to_dict()
        login_authenticate = LoginAuthenticateData(account_id, 'Mm@123').to_dict()

        def process_func(db):
            nonlocal res
            if 'id' in personnel.keys():
                bill_id = self.bill_manage_service.add_bill(OperationType.update.value,
                                                            TypeId.user.value, [user, account,
                                                                                account_role, login_authenticate],
                                                            ['PT_User', 'PT_Account', 'PT_Account_Role', 'PT_Login_Authenticate'])
                if bill_id:
                    res = 'Success'
            else:
                bill_id = self.bill_manage_service.add_bill(OperationType.add.value,
                                                            TypeId.user.value, [user, account,
                                                                                account_role, login_authenticate],
                                                            ['PT_User', 'PT_Account', 'PT_Account_Role' 'PT_Login_Authenticate'])
                if bill_id:
                    res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name, process_func,self.db_user, self.db_pwd)
        return res

    def delete_personnel(self, personne_id_list):
        '''删除人员接口

        Arguments:
            personne_id_list   {ids}      数据id
        '''
        res = 'fail'

        def process_func(db):
            nonlocal res
            ids = []
            if isinstance(personne_id_list, str):
                ids.append(personne_id_list)
            else:
                ids = personne_id_list
            for personne_id in ids:
                # 查询被删除的数据信息
                data = find_data(db, 'PT_User', {
                    'id': personne_id, 'bill_status': Status.bill_valid.value})
                if len(data) > 0:
                    self.bill_manage_service.add_bill(OperationType.delete.value,
                                                      TypeId.user.value, data[0], 'PT_User')
            res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name, process_func,self.db_user, self.db_pwd)
        return res

    def get_organizational_list(self, condition, page, count):
        '''获取组织结构列表

        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'name','level','administrative_division','organization_type']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.add_fields({
                    'name':'$organization_info.name',
                    'level':'$organization_info.level',
                    'administrative_division':'$organization_info.administrative_division',
                    'organization_type':'$organization_info.organization_type',
                    # 'superior_organization':'$superior_org.organization_info.name',
                    'id_card':"$organization_info.id_card",
                    'id_card_type':"$organization_info.id_card_type",
                    'address':'$organization_info.address',
                    'telephone':'$organization_info.telephone',
                    'contacts':'$organization_info.contacts',
                    })\
                .match_bill((C('id') == values['id']) 
                & (C('personnel_type') == UserType.Organizational) 
                & (C('name').like(values['name']))
                & (C('administrative_division').like(values['administrative_division']))
                & (C('organization_type').like(values['organization_type']))
                & (C('level').like(values['level'])))\
               .project({'_id': 0})
        res = self.page_query(
            _filter, 'PT_User', page, count)
        if res['result']:
            for result in res['result']:
                if result.get('superior_organization_id'):
                    _filter_super = MongoBillFilter()
                    _filter_super.match_bill((C('id') == result.get('superior_organization_id'))).project({'_id':0})
                    res_super = self.query(_filter_super,"PT_User")
                    if res_super:
                        result['superior_organization'] = res_super[0].get('name')
        print('>>>>>>',res)
        return res
# .lookup_bill('PT_User','superior_organization_id','id','superior_org')\
        # organizational_df = ''
        # organizational_count = 0
        # res_list = []

        # def process_func(db):
        #     nonlocal organizational_df, organizational_count, res_list
        #     collection_organizational = db['PT_User']
        #     if 'name' in condition.keys():
        #         condition['name'] = re.compile(condition['name'])
        #     condition['personnel_type'] = UserType.Organizational
        #     condition['bill_status'] = Status.bill_valid.value
        #     organizational_cur = collection_organizational.find(condition)
        #     organizational_count = collection_organizational.find(
        #         condition).count()
        #     organizational_list = list(organizational_cur)
        #     if len(organizational_list) > 0:
        #         for row in organizational_list:
        #             organizationals = row["organization_info"]
        #             organizationals['id'] = row["id"]
        #             if ('level' in condition.keys()) and (condition['level'] in organizationals.get('level')):
        #             res_list.append(organizationals)
        # process_db(self.db_addr, self.db_port, self.db_name, process_func)
        # data_List = DataList(organizational_count, res_list)
        # return data_List.to_dict()

    def update_organizational(self, organizational):
        '''# 新增/修改组织结构'''
        res = 'Fail'

        user = User().get_organizational(organizational)
        account_id = get_info({},self.session)['id']
        role_id = get_info({},self.session)['id']
        account = AccountData(account_id, user['telephone']).to_dict()
        account_role = AccountRoleData(account_id, role_id).to_dict()
        login_authenticate = LoginAuthenticateData(account_id, 'Mm@123').to_dict()
        role = RoleData(role_id, user['name'], [],user['id']).to_dict()
        def process_func(db):
            nonlocal res
            if 'id' in organizational.keys():
                bill_id = self.bill_manage_service.add_bill(OperationType.update.value,
                                                            TypeId.user.value, [user, account, account_role, login_authenticate, role], ['PT_User', 'PT_Account', 'PT_Account_Role', 'PT_Login_Authenticate', 'PT_Role'])
                if bill_id:
                    res = 'Success'
            else:
                bill_id = self.bill_manage_service.add_bill(OperationType.add.value,
                                                            TypeId.user.value, [user, account, account_role, login_authenticate, role], ['PT_User', 'PT_Account', 'PT_Account_Role', 'PT_Login_Authenticate', 'PT_Role'])
                if bill_id:
                    res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name, process_func,self.db_user, self.db_pwd)
        return res

    def delete_organizational(self, organizational_ids):
        '''删除组织机构接口

        Arguments:
            organizational_ids   {ids}      数据id
        '''
        res = 'fail'

        def process_func(db):
            nonlocal res
            ids = []
            if isinstance(organizational_ids, str):
                ids.append(organizational_ids)
            else:
                ids = organizational_ids
            for organizational_id in ids:
                # 查询被删除的数据信息
                data = find_data(db, 'PT_User', {
                    'id': organizational_id, 'bill_status': Status.bill_valid.value})
                if len(data) > 0:
                    self.bill_manage_service.add_bill(OperationType.delete.value,
                                                      TypeId.user.value, data[0], 'PT_User')
            res = 'Success'
        process_db(self.db_addr, self.db_port, self.db_name, process_func,self.db_user, self.db_pwd)
        return res

    # def get_organization_by_active(self):
    #     '''
    #     获取当前账号的组织机构
    #     '''
    #     org_id = ''
    #     def process_func(db):
    #         nonlocal org_id
    #         org_id = get_person_id(db,self.session)
    #     process_db(self.db_addr,self.db_port,self.db_name,process_func)
    #     org_list = self.get_organizational_list({'id':org_id},None,None)
    #     print('123456',org_list)
    #     return org_list

    def get_user_session(self):
        if get_user_id_or_false(self.session) == False:
            return False
        else:
            return True